<template>
  <div class="terminal-container">
    <div class="xterm-box">
      <div id="xterm" ref="xterm" class="xtermBox"></div>
    </div>
  </div>
</template>

<script>
import 'xterm/css/xterm.css'
import {Terminal} from 'xterm'
import {v4 as uuid} from 'uuid'
import {useRoute} from 'vue-router'
import Socket from '@/util/socket.js'
import {defineComponent, onUnmounted, reactive, ref, toRefs} from 'vue'

export default defineComponent({
  name: 'Xterm',
  components: {},
  setup() {
    const data = {
      rows: 50,
      data: 150,
      xterm: null,
      query: useRoute().query,
      uuid: uuid().substring(0, 8)
    }, $ref = reactive({
      xterm: ref()
    })
    const resizeScreen = () => {
      data.cols = Math.floor(window.document.documentElement.clientWidth / 15)
      data.rows = Math.floor(window.document.documentElement.clientHeight / 26)
      if (data.xterm) data.xterm.setOption({rows: this.rows, cols: this.cols});
    }
    /**
     * 初始化终端
     */
    const initXterm = (modelRef) => {
      resizeScreen()
      /* 初始化配置 */
      let term = new Terminal({
        fontSize: 18,
        rows: data.rows, // 行数
        cols: data.cols,  // 列数
        convertEol: true, // 启用时，光标将设置为下一行的开头
        scrollback: 1024, // 终端中的回滚量
        cursorBlink: true, // 光标闪烁
        LogLevel: 'debug', // 日志级别
        cursorStyle: 'bar', // 光标样式
        rendererType: 'dom', // 渲染类型
        rightClickSelectsWord: true, // 是否选中光标下的单词右击
        allowTransparency: true, // 背景是否应该支持非不透明颜色
        fontFamily: 'Consolas,Microsoft YaHei',
        theme: {
          cursor: '#CEF1FFCC', // 设置光标
          foreground: '#CEF1FFCC', // 字色
        },
        windowOptions: {
          fullscreenWin: true
        }
      })
      term.open($ref.xterm);
      /* 连接提示 */
      term.writeln('连接中...');
      term.writeln('');
      /* 输入监听 */
      term.onData((data) => {
        Socket.send({
          "command": data,
          "operate": "command"
        })
      })
      /*  建立WebSocket连接  */
      Socket.connect({
        url: `${location.host}/polymerize/echo/terminal/${data.uuid}`,
        /* 打开连接成功 */
        onOpen: () => {
          term.writeln('\x1b[1;1;32m连接成功!\n\x1b[0m')
          term.focus()
          Socket.send({
            ...modelRef,
            "operate": "connect"
          })
        },
        /* 连接出错 */
        onError: (e) => {
          term.writeln(`\x1b[1;1;31m${e}\n\x1b[0m`)
          closeXterm()
        },
        /* 收到消息回调 */
        onMessage: (e) => {
          term.write(e.data)
        },
        /* 关闭连接回调 */
        onClose: (e) => {
          term.writeln(`\x1b[1;1;31m${e.msg}\n\x1b[0m`)
          closeXterm()
        }
      })
      data.xterm = term;
      window.addEventListener("resize", resizeScreen);
    }
    /**
     * 关闭终端
     */
    const closeXterm = () => {
      /* 销毁xterm */
      data.xterm ? data.xterm.dispose() : '';
      data.xterm = null;
      data.fitAddon = null;
      /* Socket推送退出 */
      Socket.send({
        "operate": "command",
        "command": "exit"
      });
      /* 关闭Socket */
      setTimeout(() => Socket.close(), 500);
      window.addEventListener("resize", resizeScreen);
    }
    onUnmounted(() => closeXterm())
    return {
      data,
      initXterm,
      ...toRefs($ref)
    }
  }
})
</script>

<style lang="scss" scoped>
.terminal-container {

  .xterm-box {
    display: flex;
    text-align: left;
    border-radius: 5px;
    flex-direction: column;
    background: rgb(36, 41, 46);
    box-shadow: 5px 5px 20px rgba(74, 177, 227, 100);

    .xtermBox {
      flex: 1;

      ::v-deep(.xterm) {
        .xterm-screen {
          padding: 0.8rem;

          .xterm-helpers {
            height: 0 !important;
          }
        }

        .xterm-scroll-area {
          height: 0 !important;
        }
      }

      ::v-deep(.xterm-helper-textarea), ::v-deep(.xterm-char-measure-element) {
        opacity: 0;
      }
    }
  }

}
</style>
